#ifndef GAMEOBJECT_H
#define GAMEOBJECT_H

#include <vector>
#include <string>

#include "../core/glm.hpp"
#include "../core/Visitable.h"

class Transform;
class Collider;
class Renderer;
class Mesh;
class Texture;
class Behaviour;

class GameObject : public Visitable {
    protected:
        std::string name;
        glm::mat4 transform;
        Collider* collider;
        Behaviour* behaviour;

        Mesh* mesh;
        Texture* colorMap;

        GameObject* parent;

        std::vector<GameObject*> children;

    public:
        GameObject(std::string aName = NULL, glm::vec3 aPosition = glm::vec3(0.0f, 0.0f, 0.0f));
        virtual ~GameObject();

        glm::mat4 getTransform();
        void setTransform(glm::mat4);
        void translate(glm::vec3 translation);
        void rotate(float angle, glm::vec3 axis);

        const std::string getName();
        void setName(std::string);

        glm::vec3 getLocation();
        void addLocation(glm::vec3);
        void setLocation(glm::vec3);

        bool hasCollider();

        Behaviour* getBehaviour();
        void setBehaviour(Behaviour* aBehaviour);

        Collider* getCollider();
        void setCollider(Collider*);

        Mesh* getMesh();
        void setMesh(Mesh* aMesh);

        Texture* getColorMap();
        void setColorMap(Texture* aColorMap);

        virtual bool collides(GameObject* otherGameObject);
        virtual void onCollision(GameObject* otherGameObject);

        void add(GameObject* child);
        void accept(Visitor*);

        GameObject* getParent();
        std::vector<GameObject*>* getChildren();
        std::vector<GameObject*>* getAllChildren(std::vector<GameObject*>*);
        void deleteObject(GameObject*);
        glm::vec3 getAbsolutePosition();
};

#endif // GAMEOBJECT_H
